10223. Поселенцы
Катана
В игре года 1995 года в “Поселенцах
Катана” игроки пытаются доминировать на острове строя дороги, поселения и
города в неизведанной пустыне.
Вы работаете в компании –
разработчике программного обеспечения, которая только что решила разработать
компьютерную версию в этой игре, и Вы выбраны для реализации одного из особых
правил игры:
По окончании игры игрок,
построивший самую длинную дорогу, получает два дополнительных победных очка.
Проблема в том, что игроки
обычно строят сложные дорожные сети, а не только один линейный путь.
Следовательно, определение самой длинной дороги не является тривиальным делом
(хотя игроки люди обычно видят это сразу).
По сравнению с оригинальной
игрой, здесь мы рассмотрим упрощенную задачу: Вам предоставляется набор вершин
(городов) и ребер (дорог) длины 1, соединяющих вершины. Самая длинная
дорога определяется как самый длинный путь в сети, в котором не используется
ребро дважды. Однако вершины можно посещать более одного раза.
Вход.
Содержит один или несколько тестов. Первая строка каждого теста содержит два
целых числа: количество вершин n (2 ≤ n ≤ 25) и количество ребер m (1 ≤ m ≤ 25). Следующие m строк
описывают m рёбер. Каждое ребро задается номерами двух вершин,
соединенных им. Вершины пронумерованы от 0 до n – 1. Ребра
неориентированные. Вершины имеют степень три или меньше. Сеть не обязательно
является связной. Ввод завершается двумя 0 для n и m.
Выход.
Для каждого теста в отдельной строке выведите длину самой длинной дороги.
Пример входа |
Пример выхода |
3 2 0 1 1 2 15 16 0 2 1 2 2 3 3 4 3 5 4 6 5 7 6 8 7 8 7 9 8 10 9 11 10 12 11 12 10 13 12 14 0 0 |
2 12 |
графы –
перебор
Запускаем поиск в глубину из каждой вершины. Генерируем все возможные пути, используя
бектрекинг. Ограничение на количество вершин (n ≤ 25) позволяет
уложиться в отведенное время. Находим длину наибольшего пути.
Пример
Во втором
примере самый длинный путь имеет длину 12.
Реализация алгоритма
Объявим матрицу смежности графа mas.
#define MAX 26
int mas[MAX][MAX];
Заходим в вершину i. Текущее расстояние от начальной
вершины до i равно depth.
void run(int i, int depth)
{
В переменной best поддерживаем значение самого длинного
пути.
if (depth > best) best = depth;
Ищем, в какую вершину j можно попасть из i.
for (int j = 0; j < n; j++)
if (mas[i][j])
{
Удаляем ребро (i, j) и продолжаем поиск из вершины j.
mas[i][j] = mas[j][i] = 0;
run(j, depth + 1);
По возвращению из функции run восстанавливаем ребро (i,
j).
mas[i][j] = mas[j][i] = 1;
}
}
Основная часть программы. Обрабатываем
несколько тестов.
while (scanf("%d %d", &n,
&m), n + m)
{
memset(mas, 0, sizeof(mas));
Читаем входные данные. Строим граф.
for (i = 0; i < m; i++)
{
scanf("%d %d", &a,
&b);
mas[a][b] =
mas[b][a] = 1;
}
Запускаем поиск в глубину из каждой
вершины. Вершины пронумерованы от 0 до n – 1. В переменной best вычисляем максимальную длину пути.
best = 0;
for (i = 0; i < n; i++)
run(i, 0);
Выводим ответ.
printf("%d\n", best);
}
Java реализация
import java.util.*;
public class Main
{
static int g[][] = new int[26][26];
static int n, m, best;
static void run(int i, int depth)
{
if (depth > best) best = depth;
for (int j = 0; j < n; j++)
if (g[i][j] == 1)
{
g[i][j] = g[j][i] = 0;
run(j, depth + 1);
g[i][j] = g[j][i] = 1;
}
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
while(true)
{
n = con.nextInt();
m = con.nextInt();
if (n == 0 &&
m == 0) break;
for (int i = 0; i < 26; i++)
Arrays.fill(g[i], 0);
for (int i = 0; i < m; i++)
{
int a = con.nextInt();
int b = con.nextInt();
g[a][b] = g[b][a] = 1;
}
best = 0;
for (int i = 0; i < n; i++)
run(i, 0);
System.out.println(best);
}
con.close();
}
}